package cz.su.pod.reservation.ldap;

import java.util.List;

import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ldap.core.AttributesMapper;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.filter.AndFilter;
import org.springframework.ldap.filter.EqualsFilter;
import org.springframework.stereotype.Component;

import cz.su.pod.reservation.domain.LdapUser;

@Component
public class LDAPClientImpl implements LDAPClient {
	private final Logger log = LoggerFactory.getLogger(getClass());
	
	@Autowired
	private LdapTemplate ldapTemplate;
	
	@Override
	public LdapUser login(String username, String password) {
		log.debug("Attempt to login user with username = '{}'", username);
		
		AndFilter filter = new AndFilter();
		filter.and(new EqualsFilter("objectclass", "person"))
			  .and(new EqualsFilter("cn", username));
		if (ldapTemplate.authenticate("", filter.encode(), password)) {
			log.debug("User with username = '{}' login successful", username);
			return search(SearchCriteria.BY_LOGIN, username);		
		} else {
			log.debug("User with username = '{}' failed to login", username);
			return null;
		}
	}
	
	@Override
	public LdapUser search(SearchCriteria criteria, String value) {
		AndFilter filter = new AndFilter();
		filter.and(new EqualsFilter("objectclass", "person"));
		
		switch (criteria) {
			case BY_ID:
				filter.and(new EqualsFilter("uid", value));
				break;
	
			case BY_LOGIN:
				filter.and(new EqualsFilter("cn", value));
				break;
				
			default: throw new RuntimeException("Illegal criteria: " + criteria.toString());
		}
		
		List<?> ldapList = ldapTemplate.search("", filter.encode(), new LdapUserMapper());
		return (LdapUser) (ldapList != null && !ldapList.isEmpty() ? ldapList.get(0) : null);
	}
		
	
	private class LdapUserMapper implements AttributesMapper {
		@Override
		public Object mapFromAttributes(Attributes attr) throws NamingException {			
			return new LdapUser(
					String.valueOf(attr.get("uid").get()), 
					String.valueOf(attr.get("displayName").get()),
					String.valueOf(attr.get("sn").get()),
					String.valueOf(attr.get("mail").get()),
					String.valueOf(attr.get("cn").get()),
					String.valueOf(attr.get("businessCategory").get()),
					String.valueOf(attr.get("departmentNumber").get()));
		}
	}
}
